package com.tools;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.CellLocation;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;

//import android.util.Log;

public class UserLocation {

	// public static final String LAG = "LocationTest";
	private LocationManager locationManager;
	// TelephonyManager tm;
	private MyLocationListener locationListener;
	private ScheduledExecutorService locationScheduler;
	private ScheduledFuture<?> sss;
	private ScheduledFuture<?> celllocationRunnable;
	private Location location;
	private DwLocationListener dwLocationListener;

	private Context context = null;

	// 02-16 14:32:40.035: E/LocationManagerService(1286):
	// (LocationManagerService.java:861)

	public UserLocation(Context context, Handler handler) {
		this.context = context;
		this.handler = handler;
	}

	public interface DwLocationListener {
		public void onEvent(String text);
	}

	public void setDwLocationListener(DwLocationListener dwLocationListener) {
		this.dwLocationListener = dwLocationListener;
	}

	private static long startTime = 0;
	private boolean stop = false;

	public void startLocationListener() {
		if (System.currentTimeMillis() - startTime < 30 * 1000)
			return;
		startTime = System.currentTimeMillis();
		cancelTimers(true);
		removeUpdates();

		 requestNetworkLocation();
//		requestGPSLocation();
		startTimer(locationListener);
		// LOG.w("Location", "startLocationListener:"+this.hashCode());
		// }
		// requstCellLocation();
	}

	public void stopLocationListenter() {
		// Log.w("Location", "stopLocationListenter:"+this.hashCode());
		stop = true;
		cancelTimers(true);
		removeUpdates();

	}

	private void nextRequestLocation() {
		MyLog.i("nextRequestLocation" + locationListener.provider);
		if (stop)
			return;
		// Log.i("Location",
		// "nextRequestLocation:"+locationListener.provider+"   hashcode:"+this.hashCode());
		if (locationListener.provider.equals(LocationManager.GPS_PROVIDER)) {
			requestNetworkLocation();
		} else if (locationListener.provider
				.equals(LocationManager.NETWORK_PROVIDER)) {
			requestGPSLocation();
		} 
		startTimer(this.locationListener);
	}

	double latitude = 0;
	double longitude = 0;

	private void requstCellLocation() {
		MyLog.i("UserLocation:requstCellLocation");
		locationListener = new MyLocationListener("cell");
		final TelephonyManager tm = (TelephonyManager) context
				.getSystemService(Context.TELEPHONY_SERVICE);
		if (tm == null) {
			nextRequestLocation();
			return;
		}

		int phoneType = tm.getPhoneType();
		if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
			if (locationScheduler == null) {
				locationScheduler = Executors.newScheduledThreadPool(2);
			}
			celllocationRunnable = locationScheduler.schedule(new Runnable() {
				@Override
				public void run() {

					GsmCellLocation gcl = (GsmCellLocation) tm
							.getCellLocation();

					int cid = gcl.getCid();// gcl.getCid();
					int lac = gcl.getLac();// gcl.getLac();

					int mcc = Integer.valueOf(tm.getNetworkOperator()
							.substring(0, 3));// Integer.valueOf(tm.getNetworkOperator().substring(0,3));
					int mnc = Integer.valueOf(tm.getNetworkOperator()
							.substring(3, 5));// Integer.valueOf(tm.getNetworkOperator().substring(3,5));
					try {
						// 组装JSON查询字符串
						JSONObject holder = new JSONObject();
						holder.put("version", "1.1.0");
						holder.put("host", "maps.google.com");
						holder.put("address_language", "zh_CN");
						holder.put("radio_type", "gsm");
						holder.put("request_address", true);

						JSONArray array = new JSONArray();
						JSONObject data = new JSONObject();
						data.put("cell_id", cid);// cid); // 25070
						data.put("location_area_code", lac);// lac);// 4474
						data.put("mobile_country_code", mcc);// mcc);// 460
						data.put("mobile_network_code", mnc);// mnc);// 0
						data.put("timing_advance", 0);// 5555);// 0
						array.put(data);
						holder.put("cell_towers", array);

						// 创建连接，发送请求并接受回应
						DefaultHttpClient client = new DefaultHttpClient();
						HttpPost post = new HttpPost(
								"http://www.google.com/loc/json");
						StringEntity se = new StringEntity(holder.toString());
						post.setEntity(se);
						HttpResponse resp = client.execute(post);
						HttpEntity entity = resp.getEntity();
						BufferedReader br = new BufferedReader(
								new InputStreamReader(entity.getContent()));
						StringBuffer sb = new StringBuffer();
						String result = br.readLine();
						while (result != null) {
							sb.append(result + "\n");
							result = br.readLine();
						}

						JSONObject guo;
						guo = new JSONObject(sb.toString());
						guo = (JSONObject) guo.get("location");
						latitude = guo.getDouble("latitude");
						longitude = guo.getDouble("longitude");

						if ((latitude != 0) || (longitude != 0)) {
							location = new Location("network");
							location.setLatitude(latitude);
							location.setLongitude(longitude);
							return;
						}
						cancelTimers(true);
						removeUpdates();

					} catch (Exception e) {
						// e.printStackTrace();
						cancelTimers(true);
						removeUpdates();
						nextRequestLocation();
					}
				}

			}, 0, TimeUnit.SECONDS);

		} else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
			CellLocation cdmaCellLocation = tm.getCellLocation();
			if (cdmaCellLocation != null) {
				try {
					Method getBaseStationLatitude = cdmaCellLocation.getClass()
							.getMethod("getBaseStationLatitude", Void.class);
					latitude = ((Integer) getBaseStationLatitude
							.invoke(cdmaCellLocation)).intValue();
					Method getBaseStationLongitude = cdmaCellLocation
							.getClass().getMethod("getBaseStationLongitude",
									Void.class);
					longitude = ((Integer) getBaseStationLongitude
							.invoke(cdmaCellLocation)).intValue();
				} catch (Exception ex) {
					Log.w("Location", ex.getMessage());
				}
			}

			if ((latitude != 0) || (longitude != 0)) {
				latitude = latitude / 14400.0D;
				longitude = longitude / 14400.0D;
			}
		}

	}

	private void requestGPSLocation() {
		MyLog.i("UserLocation:requestGPSLocation");
	try {	boolean gpsEnabled = isGPSProviderEnabled();
		if (!gpsEnabled) {
			requestNetworkLocation();
			return;
		}
		
			locationListener = new MyLocationListener(
					LocationManager.GPS_PROVIDER);
			locationManager.requestLocationUpdates(
					LocationManager.GPS_PROVIDER, 0, 0, locationListener);
			location = locationManager
					.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void requestNetworkLocation() {
		MyLog.i("UserLocation:requestNetworkLocation");
		if (locationManager == null) {
			locationManager = (LocationManager) context
					.getSystemService(Context.LOCATION_SERVICE);
		}
		locationListener = new MyLocationListener(
				LocationManager.NETWORK_PROVIDER);
		try {
			locationManager
					.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
							1000, 0, locationListener);
		} catch (Exception e) {
		}
	}

	Handler handler;

	private void startTimer(final MyLocationListener locationListener) {
		if (locationScheduler == null) {
			locationScheduler = Executors.newScheduledThreadPool(2);
		}
		onEvent("startTimer runnable " + locationListener.provider);
		// runableList.add());
		sss = locationScheduler.schedule(new Runnable() {
			@Override
			public void run() {

				handler.post(new Runnable() {
					@Override
					public void run() {
						onEvent(locationListener.provider
								+ " timeout,into next request");
						nextRequestLocation();
					}
				});

			}
		}, 10, TimeUnit.SECONDS);
	}

	private boolean cancelTimers(boolean mayInterruptIfRunning) {
		onEvent("cancelTimer ");
		if (sss != null) {
			// locationListener.provider;
			return sss.cancel(mayInterruptIfRunning);
		} else
			return false;
	}

	public boolean isGPSProviderEnabled() {
		try {
			if (locationManager == null) {
				locationManager = (LocationManager) context
						.getSystemService(Context.LOCATION_SERVICE);
			}
			if (locationManager
					.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) {
				return true;
			}
		} catch (Exception e) {

		}
		return false;
	}

	public void removeUpdates() {
		if (locationListener == null) {
			return;
		} else if (locationListener.provider.equals("cell")) {
			onEvent("removeUpdates " + locationListener.provider);
			if (celllocationRunnable != null) {
				celllocationRunnable.cancel(true);
				celllocationRunnable = null;
			}

			return;
		}
		onEvent("removeUpdates " + locationListener.provider);
		locationManager.removeUpdates(locationListener);

		// locationListener = null;
	}

	private void updateWithNewLocation(Location location) {
		onEvent("lat:" + location.getLatitude() + " long:"
				+ location.getLongitude());

		onEvent(location.getLongitude() + "," + location.getLatitude());
	}

	private void onEvent(String text) {
		// Log.v(LAG, text);
//		if (dwLocationListener != null) {
			long time = System.currentTimeMillis();
			Date dataDate = new Date(time);
			text = dataDate.getHours() + ":" + dataDate.getMinutes() + ":"
					+ dataDate.getSeconds() + " " + text + "\n";
			MyLog.i("UserLocation:getLocation time="+text);
		/*	dwLocationListener.onEvent(text);
		}*/
	}

	class MyLocationListener implements LocationListener {
		String provider;

		public MyLocationListener(String provider) {
			this.provider = provider;
			onEvent("init LocationListener " + provider);
			removeUpdates();
		}

		@Override
		public void onLocationChanged(Location location) {
			onEvent("onLocationChanged " + provider);
			cancelTimers(true);
			removeUpdates();
			updateWithNewLocation(location);
			System.out.println("getLastKnownLocation onLocationChanged");
			// removeUpdates(this);
			if (location != null) {
				UserLocation.this.location = location;
			} else
				System.out.println("location is null");

		}

		@Override
		public void onProviderDisabled(String provider) {
			onEvent("GPS 关闭" + provider);
			cancelTimers(true);
			onEvent("into next request");
			removeUpdates();
			nextRequestLocation();
			System.out.println("getLastKnownLocation onProviderDisabled");
		}

		@Override
		public void onProviderEnabled(String provider) {
			onEvent("GPS启动" + provider);
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			onEvent("onStatusChanged" + provider + "," + status);
		}
	}

	public Location getLastKnownLocation() {
		// TODO Auto-generated method stub
		return location;
	};

}
